#include "FeedbackHelper.h"

//db
#include "mk4.h"
#include "mk4str.h"
#include "MyDataCenter.h"
#include "MyUtils.h"
#include <EIKENV.H>

extern MyDataCenter* iDataCenter;

CFeedbackHandler::CFeedbackHandler()
	:iDepth(0)
{
    m_dataid = data_dumb;
    m_rowid = -1;
    m_databaseMode = false; //if processing database field in xml?
    iDBStore = iDataCenter->iDBTemp;
	for(int i = 0; i < data_size; i++)
		iDataBuffer[i] = NULL;
}
	
CFeedbackHandler::~CFeedbackHandler()
{
	for(int i = 0; i < data_size; i++)
	{
		delete iDataBuffer[i];
	}
}
	
void CFeedbackHandler::Indent(const TInt aDepth)
{
	for (TInt i=0; i < aDepth; i++)
	{
//		_LIT(KTab, "   ");
//		iTest.Printf(KTab);
	}
}

void CFeedbackHandler::StartElement(const TQualified& aName, const RArray<TAttribute>& attributes)
{

	TPtrC elemName(aName.iLocalName);
	TPtrC elemPrefix(aName.iPrefix);
	TPtrC elemURI(aName.iURI);

	if(elemName == _L("feedback"))
	{
		m_dataid = data_func;
	}
	if(elemName == _L("desc"))
	{
		m_dataid = data_desc;
	}
	else if(elemName == _L("userid"))
	{
		m_dataid = data_userid;
	}
	else if(elemName == _L("database"))
	{
		m_dataid = data_dumb;
		m_databaseMode = true;
		iDBStore = iDataCenter->iDBInfo; //default one
	}
	else if(m_databaseMode && elemName == _L("record"))
	{
		//if really in database label
		char* ptab = (char*)m_tablename.Ptr();
		ptab[m_tablename.Length()] = '\0';
		c4_View vp = iDBStore->View(ptab); //"pms");
		c4_Row row;
		vp.Add(row);
		
		int count = vp.GetSize();
		m_rowid = count - 1;
	}

	if (elemPrefix.Length() == 0)
	{
		// locally named element
		_LIT(KElementFormatString,"LN:%S ");
		Indent(iDepth);//iTest.Printf(KElementFormatString, &elemName);
	}
	else
	{
		if (elemURI.Length() > 0)
		{
			// namespace declaration for URI
			_LIT(KNamespaceFormatString,"ELEM:%S ");
			Indent(iDepth); //iTest.Printf(KNamespaceFormatString, &elemURI);
		}
		
	
		// Fully qualified element
		_LIT(KElementFormatString, ":%S:%S ");
		Indent(iDepth);//iTest.Printf(KElementFormatString, &elemPrefix, &elemName);
	}
		
	TInt i = 0;
//	const TInt attrCount = attributes.Count() /2;
	const TInt attrCount = attributes.Count();	
	for (i = 0; i < attrCount; i++)
	{
		const TAttribute& attribute = attributes[i];
		const TPtrC attrPrefix(attribute.iName.iPrefix);
		const TPtrC attrName(attribute.iName.iLocalName);
		const TPtrC attrValue(attribute.iValue);

		if(elemName == _L("database") && attrName == _L("name"))
		{
			m_dataid = data_dumb;
			m_databaseMode = true;
			if(attrValue == _L("info"))
				iDBStore = iDataCenter->iDBInfo;
//			else if(attrValue == _L("stock"))
//				iDBStore = iDataCenter->iDBStock;
			else if(attrValue == _L("temp"))
				iDBStore = iDataCenter->iDBTemp;//神奇的临时表，空文件
//			else if(attrValue.Find(_L("image") == 0)//e.g., image001, image002
//				iDBStore = iDataCenter->imagedb(attrValue);
		}

		if(m_databaseMode && elemName == _L("table") && attrName == _L("name"))
		{
			m_tablename.Copy(attrValue);
			//如果当前是临时数据库，删除当前的临时表的所有记录
			if(iDBStore == iDataCenter->iDBTemp)
			{
				char* ptab = (char*)m_tablename.Ptr();
				ptab[m_tablename.Length()] = '\0';
				
				c4_View vp = iDBStore->View(ptab);
				vp.RemoveAll();
			}
		}

		//2008.06.09
		//only support int type, it means locate to record by integer field's value. no need add record, just change something later
		if(elemName == _L("row"))
		{
			char* ptab = (char*)m_tablename.Ptr();
			ptab[m_tablename.Length()] = '\0';
			c4_View vp = iDBStore->View(ptab);
			
			TBuf8<128> field;
			field.Copy(attrName); //data16 -> data8
			
			char* pfield = (char*)field.Ptr();
			pfield[field.Length()] = '\0';		
			
			TLex lex( attrValue );
		    TInt value;
		    lex.Val( value );
				
			m_rowid = DBUtil::Static()->FindByInt(&vp, pfield, value);
		}
		
		if(m_databaseMode && elemName == _L("field") && attrName == _L("name"))
		{
			m_fieldname.Copy(attrValue);
		}

		if(m_databaseMode && elemName == _L("field") && attrName == _L("type"))
		{
			m_fieldtype.Copy(attrValue);
			if(m_fieldtype == _L("int"))
				m_dataid = data_dbfieldInt;
			else if(m_fieldtype == _L("str"))
				m_dataid = data_dbfieldStr;
			else if(m_fieldtype == _L("bin"))
				m_dataid = data_dbfieldBin;
		}
				
		if (attrPrefix.Length() == 0)
		{
			// Locally Named attribute
			_LIT(KAttributeFormatString, "LNA:%S = %S\n");
			Indent(iDepth);//iTest.Printf(KAttributeFormatString, &attrName, &attrValue);
		}
		else
		{
			// Fully Qualified attribute
			_LIT(KAttributeFormatString, "QNA:%S:%S = %S\n");
			Indent(iDepth);//iTest.Printf(KAttributeFormatString, &attrPrefix, &attrName, &attrValue);
			
		}
	}
		
	if (i == 0)
	{
		_LIT(KNewLine, "\n");
		//iTest.Printf(KNewLine);
	}
		
	iDepth++;
	
	if(iDataBuffer[m_dataid] == NULL)
	{
		iDataBuffer[m_dataid] = iStrBuffer.AllocL();
	}
	
}
	
/*
 * 新bug,当远程record太多时，也会内存满,down
 */
void CFeedbackHandler::EndElement(const TQualified& aName)
{
	TPtrC elemName(aName.iLocalName);

	if(elemName == _L("feedback"))
	{
		m_dataid = data_dumb;
	}

	if(elemName == _L("desc"))
	{
		m_dataid = data_dumb;
	}
	
	if(elemName == _L("userid"))
	{
		m_dataid = data_dumb;
	}
	
	if(elemName == _L("field"))
	{
		m_dataid = data_dumb;
	}
	
	if(elemName == _L("record"))
	{
		if(m_rowid > 0)
		{
			char* ptab = (char*)m_tablename.Ptr();
			ptab[m_tablename.Length()] = '\0';
			c4_View vp = iDBStore->View(ptab); //"pms");
			
			c4_IntProp p1 = c4_IntProp("id");
			p1(vp[m_rowid]) = p1(vp[m_rowid-1]) + 1;
		}
		
		m_dataid = data_dumb;
	}

	if(elemName == _L("database"))
	{
		m_dataid = data_dumb;
		m_databaseMode = false;
	}
	
	if(m_databaseMode && elemName == _L("field"))
	{
		//if really in database label
		char* ptab = (char*)m_tablename.Ptr();
		ptab[m_tablename.Length()] = '\0';
		c4_View vp = iDBStore->View(ptab); //"pms");
		
//		int count = vp.GetSize();
//		if(count == 0)
//			return;
		if(m_rowid < 0)
			return;

		if(m_fieldtype == _L("int"))
		{
	 			char* p = (char*)m_fieldname.Ptr();
     			p[m_fieldname.Length()] = '\0';
     
				c4_IntProp p1 = c4_IntProp(p);
				TLex lex( iDataBuffer[data_dbfieldInt]->Des() );
			    TInt iNum;
			    lex.Val( iNum );
				p1(vp[m_rowid]) = iNum;
			    iDataBuffer[data_dbfieldInt]->Des().Copy(_L(""));				
		}
		if(m_fieldtype == _L("str"))
		{
	 			char* p = (char*)m_fieldname.Ptr();
     			p[m_fieldname.Length()] = '\0';
     
				c4_StringProp s1(p);

				TBuf8<256> temp;
				temp.Copy(iDataBuffer[data_dbfieldStr]->Des());
	 			char* ptr = (char*)temp.Ptr();
     			ptr[iDataBuffer[data_dbfieldStr]->Length()] = '\0';
				s1(vp[m_rowid]) = ptr;//iDataBuffer[data_dbfieldStr]->Ptr();
			    iDataBuffer[data_dbfieldStr]->Des().Copy(_L(""));

		}
		if(m_fieldtype == _L("bin"))
		{
	 			char* p = (char*)m_fieldname.Ptr();
     			p[m_fieldname.Length()] = '\0';
     
				c4_BytesProp b1(p);
				TPtr ptr = iDataBuffer[data_dbfieldBin]->Des();
				TUint8 * buffer = new TUint8[ptr.Length()*2];
				memcpy(buffer, ptr.Ptr(), ptr.Length() * 2);
			    c4_Bytes bin = c4_Bytes(buffer, ptr.Length()*2);
			    b1 (vp[m_rowid]) = bin;
			    iDataBuffer[data_dbfieldBin]->Des().Copy(_L(""));
			    delete buffer;
		}
		
		/*
		if(type == int)
			addint iDataBuffer[data_dbfieldint]
		else if(type = bin)
			addbin
		*/
	}
	
}
	
		
//	_LIT(KElementFormatString,"\n");
//	Indent(iDepth);//iTest.Printf(KElementFormatString);
	
void CFeedbackHandler::CharacterData(const TDesC& aData)
{
//	_LIT(KElementFormatString,"%S");
//	TPtrC tmp(aData);
//	Indent(iDepth);//iTest.Printf(KElementFormatString, &tmp);
	if(m_dataid > data_dumb)
	{
		iDataBuffer[m_dataid] = iDataBuffer[m_dataid]->ReAllocL(iDataBuffer[m_dataid]->Length() + aData.Length());
		iDataBuffer[m_dataid]->Des().Append(aData);
	}
}

void CFeedbackHandler::ProcessingInstruction(const TDesC& aTarget, const TDesC& aData)
{
	_LIT(KElementFormatString,"PI %S = %S\n");

	TPtrC target(aTarget);
	TPtrC data(aData);
	Indent(iDepth);//iTest.Printf(KElementFormatString, &target, &data);
}

void CFeedbackHandler::Comment(const TDesC& aData)
{
	_LIT(KElementFormatString,"Comment - %S\n");

	TPtrC tmp(aData);
	Indent(iDepth); //iTest.Printf(KElementFormatString, &tmp);
}
	
void CFeedbackHandler::StartCDataSection()
{
	_LIT(KDefaultFormatString,"CDATA Start\n");
	Indent(iDepth); //iTest.Printf(KDefaultFormatString);
}
	
void CFeedbackHandler::EndCDataSection()
{
	_LIT(KDefaultFormatString,"CDATA End\n");
	Indent(iDepth); //iTest.Printf(KDefaultFormatString);
}
	
void CFeedbackHandler::Default(const TDesC& aData)
{
//	_LIT(KDefaultFormatString,"Default - S\n");
//	TPtrC tmp(aData);
//	Indent(iDepth); //iTest.Printf(KDefaultFormatString, &tmp);
}

void CFeedbackHandler::SetParser(CExpatParserBase* /*aParser*/)
{
	// Does nothing
}
